import random, logging
from django.views import View
from django_redis import get_redis_connection
from django import http

from .libs.captcha.captcha import captcha
from . import constants
from meiduo_mall.utils.response_code import RETCODE
# from celery_tasks.sms.yuntongxun import CCP
from celery_tasks.sms.tasks import send_sms_code
# Create your views here.


# 手动创建日志输出
logger = logging.getLogger('django')


class SmsCodeView(View):
    """短信验证码视图"""
    def get(self, request, mobile):
        # 接收并校验参数
        image_code = request.GET.get('image_code')
        uuid = request.GET.get('uuid')
        if not all([image_code, uuid]):
            return http.HttpResponseForbidden('缺少必传参数')

        # 获取redis链接对象
        redis_conn = get_redis_connection('verify_code')

        # 判断是否是恶意请求
        redis_send_flag = redis_conn.get('send_flag_' + mobile)
        if redis_send_flag:  # 说明是恶意请求，直接返回结果，不执行后面代码
            return http.JsonResponse({'code': RETCODE.THROTTLINGERR, 'errmsg': '发送短信过于频繁'})

        # 获取redis中的图像验证码
        redis_img_code = redis_conn.get('img_code_' + uuid).decode()  # python3从redis中取的数据都是bytes类型的，需要解码成字符串

        if redis_img_code == None:  # 验证码已失效
            return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '图形验证码已失效'})

        # 删除redis中的图形验证码，防止用户恶意测试
        redis_conn.delete('img_code_' + uuid)

        # 对比图像验证码
        if redis_img_code.lower() != image_code.lower():  # 全部先转小写再比较，以提高用户体验
            return http.JsonResponse({'code': RETCODE.IMAGECODEERR, 'errmsg': '您输入的图形验证码有误'})

        # 生成短信验证码
        sms_code = '%06d' % random.randint(1, 999999)  # 生成的验证码不够6位数前面补0
        logger.info(sms_code)  # 输出验证码的日志信息

        # # 存储短信验证码
        # redis_conn.setex('sms_code_' + mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        # # 为该用户存储发送短信标志
        # redis_conn.setex('send_flag_' + mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
        # 为提升redis性能，使用redis的pipeline，因为redis和mysql都采用的是C-S架构，只能客户端向服务端请求执行命令1后才能客户端向服务端发送请求2，如果有网络延迟会造成响应慢，使用管道命令，直接把命令打包给服务端一次性执行
        # 创建redis管道
        pl = redis_conn.pipeline()
        # 将要执行的命令塞入管道
        pl.setex('sms_code_' + mobile, constants.SMS_CODE_REDIS_EXPIRES, sms_code)
        pl.setex('send_flag_' + mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
        # 执行管道中的命令
        pl.execute()

        """
        生产者消费者模式
        任务/消息：发送短信
        生产者：美多商场
        消费者：celery
        中间人：消息队列
        """
        # 发送短信验证码
        # status = CCP().send_sms(constants.SEND_SMS_TEMPLATE_ID, mobile, (sms_code, constants.SMS_CODE_REDIS_EXPIRES // 60))
        # 异步发送短信验证码 send_sms_code(mobile, sms_code)是错误的
        send_sms_code.delay(mobile, sms_code)  # 必须采用delay方法触发异步任务，调用任务，让celery作为消费者消费任务

        # # 返回结果
        # if status == 0:  # 发送短信成功
        return http.JsonResponse({'code': RETCODE.OK, 'errmsg': '发送短信成功'})
        # else:
        #     return http.JsonResponse({'code': RETCODE.MOBILEERR, 'errmsg': '发送短信失败'})


class ImageCodeView(View):
    """图形验证码视图"""
    def get(self, request, uuid):
        """
        :param request:
        :param uuid: 唯一标识当前注册用户的id
        :return: image/jpg
        """
        # 获取参数并校验
        # 生成验证码
        text, image = captcha.generate_captcha()

        # 存储验证码
        # 获取redis链接
        redis_conn = get_redis_connection('verify_code')
        # 存储验证码
        redis_conn.setex('img_code_' + uuid, constants.IMAGE_CODE_REDIS_EXPIRES, text)

        # 返回验证码
        return http.HttpResponse(image, content_type='image/jpg')

